
/*-------------------------------------------------------------------------
 *
 * string.c
 *		字符串处理助手
 *
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *	  src/common/string.c
 *
 *-------------------------------------------------------------------------
 */


#ifndef FRONTEND
#include "postgres.h"
#else
#include "postgres_fe.h"
#endif

#include "common/string.h"


/*
 * 返回字符串 `str' 是否具有后缀 `end'。
 */
bool pg_str_endswith(const char *fc_str, const char *fc_end)
{
	size_t		fc_slen = strlen(fc_str);
	size_t		fc_elen = strlen(fc_end);

	/* 不能是更长的后缀 */
	if (fc_elen > fc_slen)
		return false;

	/* 比较字符串的末尾 */
	fc_str += fc_slen - fc_elen;
	return strcmp(fc_str, fc_end) == 0;
}


/*
 * strtoint --- 像 strtol 一样，但返回 int 而不是 long
 */
int strtoint(const char *pg_restrict fc_str, char **pg_restrict fc_endptr, int fc_base)
{
	long		fc_val;

	fc_val = strtol(fc_str, fc_endptr, fc_base);
	if (fc_val != (int) fc_val)
		errno = ERANGE;
	return (int) fc_val;
}


/*
 * pg_clean_ascii -- 用 '?' 字符替换任何非 ASCII 字符
 *
 * 修改传入的字符串，该字符串必须以 '\0' 结尾。
 *
 * 此函数专门用于处理过滤掉非 ASCII 字符的情况，在一些可以让客户端提供几乎
 * 任意字符串的地方（并且没有检查以确保其为有效的用户名或
 * 数据库名称或类似内容），我们不希望控制字符或其他东西出现在
 * 日志文件中，以免服务器管理员在查看时遇到混乱的终端。
 *
 * 总的来说，这个函数不应该被使用 - 相反，考虑如何处理
 * 字符串而不需要过滤掉非 ASCII 字符。
 *
 * 从根本上讲，我们希望改善这种情况，不需要去除
 * 所有非 ASCII，而是执行更智能的过滤，这将允许 UTF 或
 * 类似的内容，但目前还不清楚我们应该允许什么，因此暂时只保留 ASCII。
 */
void pg_clean_ascii(char *fc_str)
{
	/* 只允许字符串中的清洁 ASCII 字符 */
	char	   *fc_p;

	for (fc_p = fc_str; *fc_p != '\0'; fc_p++)
	{
		if (*fc_p < 32 || *fc_p > 126)
			*fc_p = '?';
	}
}


/*
 * pg_is_ascii -- 检查字符串是否仅由 ASCII 字符组成
 */
bool pg_is_ascii(const char *fc_str)
{
	while (*fc_str)
	{
		if (IS_HIGHBIT_SET(*fc_str))
			return false;
		fc_str++;
	}
	return true;
}


/*
 * pg_strip_crlf -- 移除任何后续的换行符和回车符
 *
 * 移除输入字符串中的任何后续换行符和回车字符（Windows 上为 \r），并以零结束。
 *
 * 传入的字符串必须以零结束。此函数返回
 * 字符串的新长度。
 */
int pg_strip_crlf(char *fc_str)
{
	int			fc_len = strlen(fc_str);

	while (fc_len > 0 && (fc_str[fc_len - 1] == '\n' ||
					   fc_str[fc_len - 1] == '\r'))
		fc_str[--fc_len] = '\0';

	return fc_len;
}
